//---------------------------------------------------------------------------------
// Copyright (c) 2011, Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------

namespace Microsoft.Samples.ServiceBus.WindowsPhoneChat.Controllers
{
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using Microsoft.Samples.ServiceBus.WindowsPhoneChat.ViewModels;

    public class ViewController
    {
        static ViewController()
        {
            Current = new ViewController();
        }

        private ViewController()
        {
        }

        public static ViewController Current { get; set; }

        public void BeginInvokeUI(Action action)
        {
            App.Context.UIDispatcher.BeginInvoke(action);
        }

        public void BeginInvokeUI(Delegate d, params object[] args)
        {
            App.Context.UIDispatcher.BeginInvoke(d, args);
        }

        public void NavigateToPage(ViewModel viewModel)
        {
            var navigationEvent = new NavigationEvent(viewModel);
            navigationEvent.BeginNavigate();
        }

        public void TryUpdateViewVisualState(ViewModel viewModel)
        {
            this.BeginInvokeUI((Action<ViewModel>)TryUpdateViewVisualStateOnUIThread, viewModel);
        }

        private static void TryUpdateViewVisualStateOnUIThread(ViewModel viewModel)
        {
            var control = App.Current.RootVisual as Control;
            if (control != null)
            {
                var view = FindViewByViewModelOnUIThread(control, viewModel) as Control;
                if (view != null)
                {
                    VisualStateManager.GoToState(view, viewModel.State, true);
                }
            }
        }

        private static FrameworkElement FindViewByViewModelOnUIThread(FrameworkElement control, object viewModel)
        {
            if (control.DataContext == viewModel)
            {
                return control;
            }
            else
            {
                int childrenCount = VisualTreeHelper.GetChildrenCount(control);
                FrameworkElement[] children = new FrameworkElement[childrenCount];

                for (int i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(control, i) as FrameworkElement;
                    if (child != null)
                    {
                        if (child.DataContext == viewModel)
                        {
                            return child;
                        }
                        else
                        {
                            var view = FindViewByViewModelOnUIThread(child, viewModel);
                            if (view != null)
                            {
                                return view;
                            }
                        }
                    }
                }
            }

            return null;
        }
    }
}
